#!/usr/bin/env python3
"""
加速函数模块
实现DIFF-DEA的一阶导数和二阶导数计算，用于金叉评分系统
"""

import numpy as np
import pandas as pd
from typing import Dict, Any


class AccelerationCalculator:
    """
    加速计算器
    专门用于计算DIFF（MACD线）和DEA（信号线）的一阶导数和二阶导数
    """
    
    def __init__(self):
        """初始化加速计算器"""
        pass
    
    def calculate_first_and_second_derivatives(self, macd_line: pd.Series, signal_line: pd.Series, 
                                             lookback_days: int = 5) -> Dict[str, Any]:
        """
        计算DIFF（MACD线）和DEA（信号线）的一阶导数和二阶导数
        
        Parameters:
        - macd_line: MACD线数据 (DIFF)
        - signal_line: 信号线数据 (DEA)
        - lookback_days: 回看天数，默认5天
        
        Returns:
        dict: 包含一阶导数、二阶导数及相关分析结果
        """
        try:
            if len(macd_line) < lookback_days + 2:
                return self._get_empty_result()
            
            # 获取最近的数据
            recent_macd = macd_line.iloc[-lookback_days:]
            recent_signal = signal_line.iloc[-lookback_days:]
            
            # 计算DIFF的一阶导数（速度）
            diff_first_derivative = self._calculate_first_derivative(recent_macd.values)
            
            # 计算DIFF的二阶导数（加速度）
            diff_second_derivative = self._calculate_second_derivative(recent_macd.values)
            
            # 计算DEA的一阶导数（速度）
            dea_first_derivative = self._calculate_first_derivative(recent_signal.values)
            
            # 计算DEA的二阶导数（加速度）
            dea_second_derivative = self._calculate_second_derivative(recent_signal.values)
            
            # 计算相对导数（DIFF相对于DEA的优势）
            relative_first_derivative = diff_first_derivative - dea_first_derivative if diff_first_derivative is not None and dea_first_derivative is not None else 0
            relative_second_derivative = diff_second_derivative - dea_second_derivative if diff_second_derivative is not None and dea_second_derivative is not None else 0
            
            # 计算导数强度评分（0-100分）
            derivative_strength = self._evaluate_derivative_strength(
                diff_first_derivative, 
                diff_second_derivative,
                relative_first_derivative,
                relative_second_derivative
            )
            
            # 判断动量质量
            momentum_quality = self._classify_momentum_quality(
                derivative_strength,
                diff_first_derivative,
                diff_second_derivative
            )
            
            return {
                'diff_first_derivative': diff_first_derivative,
                'diff_second_derivative': diff_second_derivative,
                'dea_first_derivative': dea_first_derivative,
                'dea_second_derivative': dea_second_derivative,
                'relative_first_derivative': relative_first_derivative,
                'relative_second_derivative': relative_second_derivative,
                'derivative_strength': derivative_strength,
                'momentum_quality': momentum_quality,
                'success': True
            }
            
        except Exception as e:
            return self._get_error_result(str(e))
    
    def _calculate_first_derivative(self, values: np.ndarray) -> float:
        """
        计算一阶导数（速度）
        
        Parameters:
        - values: 数值数组
        
        Returns:
        float: 一阶导数（最近的值）
        """
        if len(values) < 2:
            return 0
        
        # 计算差分
        first_derivative = np.diff(values)
        # 返回最近的值
        return first_derivative[-1] if len(first_derivative) > 0 else 0
    
    def _calculate_second_derivative(self, values: np.ndarray) -> float:
        """
        计算二阶导数（加速度）
        
        Parameters:
        - values: 数值数组
        
        Returns:
        float: 二阶导数（最近的值）
        """
        if len(values) < 3:
            return 0
        
        # 计算一阶导数
        first_derivative = np.diff(values)
        # 计算二阶导数
        if len(first_derivative) > 1:
            second_derivative = np.diff(first_derivative)
            # 返回最近的值
            return second_derivative[-1] if len(second_derivative) > 0 else 0
        return 0
    
    def _evaluate_derivative_strength(self, diff_first_derivative: float, diff_second_derivative: float,
                                    relative_first_derivative: float, relative_second_derivative: float) -> float:
        """
        评估导数强度（0-100分）
        重点奖励DIFF的一阶导数和二阶导数都为正且较大的情况
        
        Parameters:
        - diff_first_derivative: DIFF的一阶导数
        - diff_second_derivative: DIFF的二阶导数
        - relative_first_derivative: 相对一阶导数
        - relative_second_derivative: 相对二阶导数
        
        Returns:
        float: 导数强度评分（0-100）
        """
        try:
            # 1. DIFF一阶导数评分（权重40%）
            if diff_first_derivative > 0.02:  # 极强向上速度
                first_deriv_score = 100
            elif diff_first_derivative > 0.01:  # 强向上速度
                first_deriv_score = 90
            elif diff_first_derivative > 0.005:  # 中等向上速度
                first_deriv_score = 80
            elif diff_first_derivative > 0.002:  # 轻微向上速度
                first_deriv_score = 70
            elif diff_first_derivative > 0:  # 微弱向上速度
                first_deriv_score = 60
            elif diff_first_derivative > -0.002:  # 接近零速度
                first_deriv_score = 50
            elif diff_first_derivative > -0.005:  # 轻微向下速度
                first_deriv_score = 40
            elif diff_first_derivative > -0.01:  # 中等向下速度
                first_deriv_score = 30
            else:  # 强烈向下速度
                first_deriv_score = 20
            
            # 2. DIFF二阶导数评分（权重40%）
            if diff_second_derivative > 0.01:  # 极强向上加速度
                second_deriv_score = 100
            elif diff_second_derivative > 0.005:  # 强向上加速度
                second_deriv_score = 90
            elif diff_second_derivative > 0.002:  # 中等向上加速度
                second_deriv_score = 80
            elif diff_second_derivative > 0:  # 轻微向上加速度
                second_deriv_score = 70
            elif diff_second_derivative > -0.002:  # 接近零加速度
                second_deriv_score = 50
            elif diff_second_derivative > -0.005:  # 轻微向下加速度
                second_deriv_score = 40
            elif diff_second_derivative > -0.01:  # 中等向下加速度
                second_deriv_score = 30
            else:  # 强烈向下加速度
                second_deriv_score = 20
            
            # 3. 相对一阶导数评分（权重10%）
            if relative_first_derivative > 0.01:  # 明显优势
                relative_first_score = 100
            elif relative_first_derivative > 0.005:  # 中等优势
                relative_first_score = 85
            elif relative_first_derivative > 0:  # 轻微优势
                relative_first_score = 70
            elif relative_first_derivative > -0.005:  # 接近
                relative_first_score = 50
            else:  # 劣势
                relative_first_score = 30
            
            # 4. 相对二阶导数评分（权重10%）
            if relative_second_derivative > 0.005:  # 明显优势
                relative_second_score = 100
            elif relative_second_derivative > 0.002:  # 中等优势
                relative_second_score = 85
            elif relative_second_derivative > 0:  # 轻微优势
                relative_second_score = 70
            elif relative_second_derivative > -0.002:  # 接近
                relative_second_score = 50
            else:  # 劣势
                relative_second_score = 30
            
            # 综合评分
            final_score = (
                first_deriv_score * 0.4 +
                second_deriv_score * 0.4 +
                relative_first_score * 0.1 +
                relative_second_score * 0.1
            )
            
            return min(100, max(0, final_score))
            
        except Exception:
            return 50
    
    def _classify_momentum_quality(self, derivative_strength: float, 
                                  diff_first_derivative: float, 
                                  diff_second_derivative: float) -> str:
        """
        根据导数强度分类动量质量
        
        Parameters:
        - derivative_strength: 导数强度评分
        - diff_first_derivative: DIFF的一阶导数
        - diff_second_derivative: DIFF的二阶导数
        
        Returns:
        str: 动量质量分类
        """
        if (derivative_strength >= 90 and 
            diff_first_derivative > 0.01 and 
            diff_second_derivative > 0.005):
            return 'explosive'  # 爆发性动量
        elif (derivative_strength >= 80 and 
              diff_first_derivative > 0.005 and 
              diff_second_derivative > 0.002):
            return 'strong'  # 强劲动量
        elif (derivative_strength >= 70 and 
              diff_first_derivative > 0):
            return 'moderate'  # 中等动量
        elif derivative_strength >= 60:
            return 'weak'  # 弱动量
        else:
            return 'declining'  # 衰减动量
    
    def _get_empty_result(self) -> Dict[str, Any]:
        """返回空结果"""
        return {
            'diff_first_derivative': 0,
            'diff_second_derivative': 0,
            'dea_first_derivative': 0,
            'dea_second_derivative': 0,
            'relative_first_derivative': 0,
            'relative_second_derivative': 0,
            'derivative_strength': 0,
            'momentum_quality': 'insufficient_data',
            'success': False
        }
    
    def _get_error_result(self, error_msg: str) -> Dict[str, Any]:
        """返回错误结果"""
        return {
            'diff_first_derivative': 0,
            'diff_second_derivative': 0,
            'dea_first_derivative': 0,
            'dea_second_derivative': 0,
            'relative_first_derivative': 0,
            'relative_second_derivative': 0,
            'derivative_strength': 0,
            'momentum_quality': 'calculation_error',
            'success': False,
            'error': error_msg
        }


# 便捷函数
def calculate_derivatives(macd_line: pd.Series, signal_line: pd.Series, lookback_days: int = 5) -> Dict[str, Any]:
    """
    便捷函数：计算DIFF-DEA的一阶导数和二阶导数
    
    Parameters:
    - macd_line: MACD线数据 (DIFF)
    - signal_line: 信号线数据 (DEA)
    - lookback_days: 回看天数，默认5天
    
    Returns:
    dict: 包含一阶导数、二阶导数及相关分析结果
    """
    calculator = AccelerationCalculator()
    return calculator.calculate_first_and_second_derivatives(macd_line, signal_line, lookback_days)


if __name__ == "__main__":
    # 示例用法
    print("加速函数模块已创建")